package router

import (
	"Forum/controller"
	_ "Forum/docs" // 千万不要忘了导入把你上一步生成的docs
	"Forum/logger"
	"Forum/middlewares"
	"Forum/pkg/jwt"
	"github.com/gin-gonic/gin"
	swaggerFiles "github.com/swaggo/files"
	gs "github.com/swaggo/gin-swagger"
	"net/http"
	"strings"
	"time"
)

// Setup函数用于初始化并配置gin框架，设置中间件和路由
// 返回值: *gin.Engine，初始化后的gin引擎实例
func Setup(mode string) *gin.Engine {
	if mode == gin.ReleaseMode {
		gin.SetMode(gin.ReleaseMode) // gin 设置成发布模式
	}
	// 创建一个新的gin引擎实例
	r := gin.New()
	// 使用自定义的日志记录和异常恢复中间件
	r.Use(logger.GinLogger(), logger.GinRecovery(true))

	r.GET("/swagger/*any", gs.WrapHandler(swaggerFiles.Handler)) // swag-gin

	v1 := r.Group("/api/v1")
	// 注册路由业务
	v1.POST("/signup", controller.SignUpHandler)
	v1.POST("/login", controller.LoginHandler)
	// JWT认证 + 令牌桶限流
	v1.Use(middlewares.JWTAuthMiddleware(), middlewares.RateLimitMiddleware(time.Second*1, 100))
	{
		v1.GET("/community", controller.CommunityHandler)                          // 社区列表
		v1.GET("/community/:id", controller.CommunityDetailHandler)                // 社区详情
		v1.GET("/community/post/list/:id", controller.GetCommunityPostListHandler) // 根据社区id返回对应社区下的帖子
		v1.POST("/community/post", controller.CreatePostHandler)                   // 创建帖子
		v1.GET("/community/post/:id", controller.PostDetailHandler)                // 帖子详情
		v1.GET("/community/post/list", controller.GetPostListHandler)              // 帖子列表
		v1.GET("/community/post/orderList", controller.GetPostOrderListHandler)    // 排序返回帖子列表
		v1.POST("/community/vote", controller.CommunityVote)                       // 帖子投票
		v1.POST("/comment", controller.CommentHandler)                             // 帖子评论
		v1.GET("/comment", controller.CommentListHandler)                          // 帖子评论列表
	}

	// 配置GET请求的路由，处理根路径的请求
	r.GET("/", func(c *gin.Context) {
		// 响应客户端请求，返回HTTP状态码200和字符串"ok"
		c.String(http.StatusOK, "ok")
	})
	// 返回初始化后的gin引擎实例
	return r
}

// JWTAuthMiddleware 基于JWT的认证中间件
func JWTAuthMiddleware() func(c *gin.Context) {
	return func(c *gin.Context) {
		// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
		// 这里假设Token放在Header的Authorization中，并使用Bearer开头
		// Authorization: Bearer xxxxxxx.xxx.xxxxxxx
		// 这里的具体实现方式要依据实际业务情况决定
		authHeader := c.Request.Header.Get("Authorization")
		if authHeader == "" {
			c.JSON(http.StatusOK, gin.H{
				"code": 2003,
				"msg":  "请求头中auth为空",
			})
			c.Abort()
			return
		}
		// 按空格分割
		parts := strings.SplitN(authHeader, " ", 2)
		if !(len(parts) == 2 && parts[0] == "Bearer") {
			c.JSON(http.StatusOK, gin.H{
				"code": 2004,
				"msg":  "请求头中auth格式有误",
			})
			c.Abort()
			return
		}
		// parts[1]是获取到的tokenString，我们使用之前定义好的解析JWT的函数来解析它
		mc, err := jwt.ParseToken(parts[1])
		if err != nil {
			c.JSON(http.StatusOK, gin.H{
				"code": 2005,
				"msg":  "无效的Token",
			})
			c.Abort()
			return
		}
		// 将当前请求的userID信息保存到请求的上下文c上
		c.Set("userID", mc.UserID)
		c.Next() // 后续的处理函数可以用过c.Get("username")来获取当前请求的用户信息
	}
}
